﻿using System;
using System.Windows.Forms;
using DevComponents.AdvTree;
using EventMgrLib;
using Force.DeepCloner;
using SmartMotion.Core;
using Sunny.UI;
using WeifenLuo.WinFormsUI.Docking;

namespace SmartMotion.Pages.DockPages
{
    public partial class FrmEdit : DockContent
    {
        private Flow _flow;
        private EventMgr _em;
        public FrmEdit()
        {
            InitializeComponent();
        }

        private void FrmEdit_Load(object sender, EventArgs e)
        {
            
            _em = EventMgr.Ins;
            _em.GetEvent<RunActionItem>().Subscribe(RunItem);
            _em.GetEvent<DellFlow>().Subscribe(DelFlow, flowName => flowName == _flow.Name);
            _em.GetEvent<RenameFlow>().Subscribe(Rename,flow=>flow==_flow);
        }

        private void FrmEdit_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            _em.GetEvent<RunActionItem>().Unsubscribe(RunItem);
            _em.GetEvent<DellFlow>().Unsubscribe(DelFlow);
            _em.GetEvent<RenameFlow>().Unsubscribe(Rename);
        }

        private void Rename(Flow flow)
        {   
            this.Text = flow.Name;
        }

        private void DelFlow(string flowName)
        {
            Close();
        }   
            
        public void LoadFlow(Flow flow)
        {
            _flow = flow;
            //把Flow数据结构转化为treeView
            tv.Nodes.Clear();
            NodeCollection nodes = Flow2Tree(_flow.Nodes);//流程的节点集合转换为Tree的节点集合
            foreach (Node node in nodes)
            {
                tv.Nodes.Add(node);
            }
            tv.ExpandAll();
        }

        private void RunItem(ActionItem actionItem)
        {
            var node = FindNode(tv.Nodes, actionItem);
            if (node==null) return;
            node.Cells[0].Text = actionItem.ItemName;
            node.Cells[1].Checked = actionItem.InUse;
            node.Cells[3].Text = actionItem.State;
            node.Cells[4].Text = actionItem.Time.ToString();
            node.Cells[5].Text = actionItem.Description;
        }

        /// <summary>
        /// 查找节点
        /// </summary>
        /// <param name="nodes">所有节点集合</param>
        /// <param name="actionItem">actionItem</param>
        /// <returns></returns>
        private Node FindNode(NodeCollection nodes, ActionItem actionItem)
        {
            foreach (Node node in nodes)
            {
                if (node.Tag == actionItem) return node;//如果本节点是，直接返回
                var findNode = FindNode(node.Nodes, actionItem);//在子节点里找
                if (findNode!=null) return findNode;//子节点里找到了
            }
            return null;//没找到
        }

        /// <summary>   
        /// 流程显示到树上
        /// </summary>
        /// <param name="nodes"></param>
        /// <returns></returns>
        private NodeCollection Flow2Tree(ActionItemConnection nodes)
        {
            NodeCollection nodeCollection = new NodeCollection();

            foreach (ActionItem actionItem in nodes)
            {
                Node advNode = CreateNodeFromActionItem(actionItem);
                nodeCollection.Add(advNode);
                NodeCollection nodesAdd = Flow2Tree(actionItem.Nodes);
                foreach (Node node in nodesAdd)
                {
                    advNode.Nodes.Add(node);
                }
            }

            return nodeCollection;

        }

        Node CreateNodeFromActionItem(ActionItem item)
        {
            Node node = new Node(item.ItemName);//自定义名称，可以改
            node.Tag = item;
            node.Cells.Add(new Cell() { CheckBoxVisible = true, Checked = item.InUse });
            var cell = new Cell(item.ItemName);
            cell.Images.Image = item.IconImage;
            node.Cells.Add(cell);//图标+名称
            node.Cells.Add(new Cell(item.State));
            node.Cells.Add(new Cell(item.Time.ToString()));
            node.Cells.Add(new Cell(item.Description));
            return node;
        }

        /// <summary>
        /// 每次拖拽后触发这个事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tv_AfterNodeDrop(object sender, DevComponents.AdvTree.TreeDragDropEventArgs e)
        {
            //把treeView 转化为Flow
            if (e.IsCopy)
            {
                e.Node.Tag = e.Node.Tag.DeepClone();//Ctrl+拖动复制一行后，需要深度克隆，不然两行是同一个对象
            }
            _flow.Nodes = Tree2Flow(tv.Nodes);//Tree的节点集合转给Flow的节点集合
        }

        private ActionItemConnection Tree2Flow(NodeCollection tvNodes)
        {
            ActionItemConnection con = new ActionItemConnection();
            foreach (Node tvNode in tvNodes)
            {
                ActionItem actionNode = (ActionItem) tvNode.Tag;
                con.Add(actionNode);
                actionNode.Nodes = Tree2Flow(tvNode.Nodes);
            }

            return con;
        }

        private void tv_NodeClick(object sender, DevComponents.AdvTree.TreeNodeMouseEventArgs e)
        {
            var node = e.Node;
            ActionItem actionItem = (ActionItem) node.Tag;
            if (actionItem!=null)
            {
                _em.GetEvent<SelectedObjectChanged>().Publish(actionItem);//用于属性窗体绑定
                _em.GetEvent<SelectActionChanged>().Publish(actionItem);//用于告诉外面的停靠面板所在的窗体哪一项被选中
            }
        }

        private void tv_AfterCellEditComplete(object sender, CellEditEventArgs e)
        {
            var node = tv.SelectedNode;
            ActionItem editActionItem = (ActionItem)node.Tag;
            editActionItem.Name = node.Cells[0].Text;
            editActionItem.InUse = node.Cells[1].Checked;
            editActionItem.Description = node.Cells[5].Text;
        }

        private void tv_AfterCheck(object sender, AdvTreeCellEventArgs e)
        {
            var node = tv.SelectedNode;
            ActionItem editActionItem = (ActionItem)node.Tag;
            editActionItem.InUse = node.Cells[1].Checked;
        }

        private void tv_NodeDoubleClick(object sender, TreeNodeMouseEventArgs e)
        {
            var node = e.Node;
            ActionItem actionNode = (ActionItem)node.Tag;
            if (actionNode != null)
            {
                if (actionNode.GetConfigForm() is UIForm configForm)
                {
                    configForm.ShowDialog();
                    tv.SelectNode(node, eTreeAction.Mouse);
                }
            }
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DelNode();
        }

        private void DelNode()
        {
            if (tv.SelectedNode != null)
            {
                if (RemoveNode(tv.Nodes, tv.SelectedNode))
                {
                    _flow.Nodes =Tree2Flow(tv.Nodes);
                }
            }
        }

        bool RemoveNode(NodeCollection nodes, Node node)
        {
            if (nodes.Contains(node))
            {
                nodes.Remove(node);
                return true;
            }
            else
            {
                foreach (Node node1 in nodes)
                {
                    if (RemoveNode(node1.Nodes,node))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        private void FrmEdit_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyCode==Keys.Delete)
            {
                DelNode();
            }
        }
    }
}
